package com.atguigu.filter;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.result.RetVal;
import com.atguigu.result.RetValCodeEnum;
import com.atguigu.util.IpUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.List;

//全局拦截器
public class AccessFilter implements GlobalFilter {
    @Value("${filter.whiteList}")
    private String filterWhiteList;
    @Autowired
    private RedisTemplate redisTemplate;
    AntPathMatcher antPathMatcher = new AntPathMatcher();//正则
    @Override
    //exchange服务交换机,储存请求和响应的属性,是一个不可变得实例
    //chain网关过滤连表,用于过滤去链式调用
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //对于内部接口不允许外部访问,
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getURI().getPath();
        //获取用户的临时id 为了在购物车的时候用
        String userTempId = getUserTempId(request);
        //获取用户登录id
        String userId = getUserId(request);
        //如果用户换了一个网络环境
        if ("-1".equals(userId)){
            return writeDataToBrowser(exchange,RetValCodeEnum.NO_PERMISSION);
        }
        //如果请求路径中包含sku我们就让它不能访问,提示没有权限
        if (antPathMatcher.match("/sku/**",path)){
            //把信息写给浏览器
            return writeDataToBrowser(exchange,RetValCodeEnum.NO_PERMISSION);
        }
        //请求白名单必须跳转到登陆
        for (String filterWhite:filterWhiteList.split(",")){
            if(path.indexOf(filterWhite)!=-1&& StringUtils.isEmpty(userId)){
                //让它跳转到登录页面
                ServerHttpResponse response = exchange.getResponse();
                response.setStatusCode(HttpStatus.SEE_OTHER);
                response.getHeaders().set(HttpHeaders.LOCATION,"http://passport.gmall.com/login.html?originalUrl="+request.getURI());
                return response.setComplete();
            }
        }
        //5,把用户id信息保存到header中,传给shop-web那边的request;
        if (!StringUtils.isEmpty(userId)||!StringUtils.isEmpty(userTempId)){
            if(!StringUtils.isEmpty(userId)){
                request.mutate().header("userId",userId).build();
            }
            if(!StringUtils.isEmpty(userTempId)){
                request.mutate().header("userTempId",userTempId).build();
            }
            //过滤器放开拦截 让下游继续执行(修改了exchange)
            return chain.filter(exchange.mutate().request(request).build());
        }

        //如果不想拦截 就放开
        return chain.filter(exchange);
    }
    private String getUserId(ServerHttpRequest request) {
        //a.获取登录后的token
        List<String> headerValueList = request.getHeaders().get("token");
        String token = "";
        if (!CollectionUtils.isEmpty(headerValueList)) {
            token = headerValueList.get(0);
        } else {
            HttpCookie cookie = request.getCookies().getFirst("token");
            if (cookie == null) {

                return token = cookie.getValue();
            }
        }
        //通过token拼接从redis中拿到userId
        if (!StringUtils.isEmpty(token)){
            String userKey= "user:login:"+token;
            JSONObject loginJSONObject =(JSONObject) redisTemplate.opsForValue().get(userKey);
            if (loginJSONObject!=null){
                //判断是否在同一个网络环境
                String loginIp = loginJSONObject.getString("loginIp");
                //拿到当前电脑所处环境的ip地址
                String gatwayIpAddress = IpUtil.getGatwayIpAddress(request);
                if (loginIp.equals(gatwayIpAddress)){
                    return  loginJSONObject.getString("userId");
                }else{
                    //返回一个错误标识
                    return "-1";
                }
            }
        }
        return null;
    }

    private String getUserTempId(ServerHttpRequest request) {
        List<String> headerValueList = request.getHeaders().get("userTempId");
        String userTempId="";
        if(!CollectionUtils.isEmpty(headerValueList)){
            userTempId=headerValueList.get(0);
        }else{
            HttpCookie cookie = request.getCookies().getFirst("userTempId");
            if(cookie!=null){
                userTempId=cookie.getValue();
            }
        }
        return userTempId;
    }


    //把信息返回给浏览器
    private Mono<Void> writeDataToBrowser(ServerWebExchange exchange, RetValCodeEnum retValCodeEnum) {
        //匹配路径的对象
        AntPathMatcher antPathMatcher = new AntPathMatcher();//正则
        ServerHttpResponse response = exchange.getResponse();
        //设置返回给浏览器的数据类型 数据类型为json
        response.getHeaders().add("Content-Type","application/json;charset=UTF-8");
        //传递的数据是什么
        RetVal<Object> retVal = RetVal.build(null, retValCodeEnum);
        //把数据转换成json字符串
        byte[] retBytes = JSONObject.toJSONString(retVal).getBytes(StandardCharsets.UTF_8);
        //需要DataBuffer参数,搞一个
        DataBuffer dataBuffer = response.bufferFactory().wrap(retBytes);
        return response.writeWith(Mono.just(dataBuffer));

    }
}
